﻿// // ******************************************************************
// //       /\ /|       @file       TranslationServicesCommandHandler.cs
// //       \ V/        @brief      await29
// //       | "")       @author     Await, 285283010@qq.com
// //       /  |
// //      /  \\        @Modified   2025-03-02 18:03
// //    *(__\_\        @Copyright  Copyright (c) , 2025-02-23 10:02 Await
// // ******************************************************************

using System.Text;
using AutomaticSubtitles.Contracts.Dto;
using AutomaticSubtitles.Contracts.Vo;
using AutomaticSubtitles.Service.Application.Media.Queries;
using AutomaticSubtitles.Service.Application.Translate.Commands;
using AutomaticSubtitles.Service.Application.Translate.Service.Commands;
using AutomaticSubtitles.Service.Application.Translate.Service.Queries;
using AutomaticSubtitles.Service.DataAccess.Model;
using AutomaticSubtitles.Service.Domain.Media;
using AutomaticSubtitles.Service.Domain.Translate;
using AutomaticSubtitles.Service.Application.TranslationRecord.Commands;
using AutomaticSubtitles.Service.Infrastructure.Helper;
using AutomaticSubtitles.Service.Infrastructure.Configuration;
using Xabe.FFmpeg;
using System.IO;
using System.Runtime.InteropServices;
using System.Reflection;
using AutomaticSubtitles.Service.Application.LanguageConversion.Queries;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;

namespace AutomaticSubtitles.Service.Application.Translate.Service;

public class TranslationServicesCommandHandler : BaseAutoService
{
    private readonly IEventBus _eventBus;
    private readonly ILogger<TranslationServicesCommandHandler> _logger;
    private readonly IMediaRepository _mediaRepository;
    private readonly ISubtitleRepository _repository;
    private readonly SubtitleExtractionConfig _subtitleConfig;
    private readonly ITranslateRepository _translateRepository;

    // 添加翻译记录缓存字典，键为"源语言:目标语言:原文"，值为翻译结果
    private readonly Dictionary<string, string> _translationCache = new();

    public TranslationServicesCommandHandler(
        ISubtitleRepository repository,
        IEventBus eventBus,
        ILogger<TranslationServicesCommandHandler> logger,
        ITranslateRepository translateRepository,
        IMediaRepository mediaRepository,
        SubtitleExtractionConfig subtitleConfig)
    {
        _repository = repository;
        _eventBus = eventBus;
        _logger = logger;
        _translateRepository = translateRepository;
        _mediaRepository = mediaRepository;
        _subtitleConfig = subtitleConfig;
    }

    [EventHandler]
    public async Task Handle(SubtitleTranslationCommand command)
    {
        //TODO:语言对应转换此处未完成
        //TODO:翻译做成并发操作 待完成
        foreach (var keyValuePair in command.data)
        {
            var msgLog = $"--开始翻译{keyValuePair.Key}";
            _logger.LogInformation(msgLog);
            var subPath = string.Empty;
            foreach (var autoMedia in keyValuePair.Value)
            {
                var subtitle = (await _repository.GetListAsync(x => x.VideoId.Equals(autoMedia.Id)))?.ToList();
                if (subtitle == null || subtitle.Count == 0)
                {
                    var msg = $"--未找到视频{autoMedia.Name}的字幕文件，尝试从音频提取字幕";
                    _logger.LogWarning(msg);

                    // 调用音频翻译
                    var extractedSubtitle = await ExtractSubtitleFromAudio(autoMedia);
                    if (extractedSubtitle != null)
                    {
                        subtitle = [extractedSubtitle];
                        _logger.LogInformation($"--成功从音频提取字幕：{extractedSubtitle.Path}");
                    }
                    else
                    {
                        _logger.LogWarning($"--无法从音频提取字幕，跳过翻译操作");
                        continue;
                    }
                }

                if (subtitle.Count == 0) continue;
                var firstOrDefault = subtitle.FirstOrDefault(x => x.IsDefault) ?? subtitle.FirstOrDefault();
                var getLanguageConversionQuery = new GetLanguageConversionQuery([keyValuePair.Key]);
                await _eventBus.PublishAsync(getLanguageConversionQuery);
                if (firstOrDefault == null || getLanguageConversionQuery.Result.Select(x => x.Key).Any(x => x == firstOrDefault.Language))
                {
                    _logger.LogWarning($"--未找到默认字幕或字幕语言与目标语言相同，跳过翻译操作");
                    continue;
                }

                var startTranslationOperationCommand = new StartTranslationOperationCommand(firstOrDefault, keyValuePair.Key);
                await _eventBus.PublishAsync(startTranslationOperationCommand);
                if (startTranslationOperationCommand.Result == null) continue;
                command.Result ??= [];
                subPath = startTranslationOperationCommand.Result;
                command.Result.Add(subPath); //翻译后的字幕地址

                // 添加翻译记录
                var addRecordCommand = new AddTranslationRecordCommand(
                    autoMedia,
                    startTranslationOperationCommand.Result,
                    startTranslationOperationCommand.targetLanguage
                );
                await _eventBus.PublishAsync(addRecordCommand);

                var msgM = $"--媒体：{autoMedia.Name} {keyValuePair.Key} 字幕翻译完成！地址：{subPath}";
                _logger.LogWarning(msgM);
            }

            var msgEnd = $"--翻译{keyValuePair.Key}完成！";
            _logger.LogInformation(msgEnd);
        }
    }

    /// <summary>
    /// 从音频提取字幕，支持Windows和Linux环境
    /// </summary>
    /// <param name="media">媒体信息</param>
    /// <returns>提取的字幕实体</returns>
    private async Task<Auto_Subtitle?> ExtractSubtitleFromAudio(Auto_Media media)
    {
        var mediaPath = media.Path;
        if (!File.Exists(mediaPath))
        {
            _logger.LogWarning($"媒体文件不存在: {mediaPath}");
            return null;
        }

        // 记录当前运行环境信息
        _logger.LogInformation($"当前运行环境: {RuntimeInformation.OSDescription}, 架构: {RuntimeInformation.ProcessArchitecture}");

        try
        {
            // 获取媒体信息
            var mediaInfo = await FFmpeg.GetMediaInfo(mediaPath);

            // 获取所有音频流
            var audioStreams = mediaInfo.AudioStreams.ToList();
            if (!audioStreams.Any())
            {
                _logger.LogWarning($"没有找到音频流: {mediaPath}");
                return null;
            }

            _logger.LogInformation($"媒体 '{media.Name}' 包含 {audioStreams.Count} 个音频流，将尝试提取字幕");

            // 创建临时目录基础路径
            var baseTempDir = Path.Combine(Common.GlobalPath, "SubtitleExtracted");
            Directory.CreateDirectory(baseTempDir); // 确保目录存在
            var fileName = Path.GetFileNameWithoutExtension(mediaPath);

            // 跟踪是否至少有一个音频流成功处理
            var anyStreamProcessed = false;
            string finalSubtitlePath = null;
            Exception lastException = null;
            var detectedLanguage = "auto";

            // 逐个尝试提取字幕
            foreach (var audioStream in audioStreams)
                try
                {
                    _logger.LogInformation($"尝试从音频流 {audioStream.Index} 提取字幕");

                    // 设置Whisper选项
                    var options = new AudioSubtitleHelper.WhisperOptions
                    {
                        Language = "auto", // 使用自动语言检测
                        SampleRate = 16000
                    };

                    // 根据平台设置特定选项
                    if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                    {
                        _logger.LogInformation("Linux环境: 应用特定设置");

                        // 检查Whisper相关库
                        var assemblyLocation = Assembly.GetExecutingAssembly().Location;
                        var assemblyDirectory = Path.GetDirectoryName(assemblyLocation);
                        var runtimePath = Path.Combine(assemblyDirectory, "runtimes", "linux-x64", "native");

                        if (Directory.Exists(runtimePath))
                        {
                            var libFiles = Directory.GetFiles(runtimePath, "libwhisper.*");
                            _logger.LogInformation($"Linux环境: 库文件检查: {runtimePath}, 找到 {libFiles.Length} 个匹配文件");
                        }
                    }

                    // 创建进度报告对象
                    var progress = new Progress<AudioSubtitleHelper.ProcessProgress>(p =>
                    {
                        _logger.LogInformation($"--字幕提取进度 [音频流 {audioStream.Index}]：{p.Stage} {p.Percentage:F1}% - {p.Details}");
                    });

                    // 设置临时输出字幕文件路径
                    var tempSrtFilePath = Path.Combine(baseTempDir, $"{fileName}_temp_{audioStream.Index}.srt");

                    try
                    {
                        // 使用AudioSubtitleHelper提取字幕
                        var result = await AudioSubtitleHelper.ExtractSubtitleFromAudioAsync(
                            audioStream,
                            tempSrtFilePath,
                            options,
                            progress,
                            media.Name
                        );

                        // 获取生成的字幕文件路径
                        finalSubtitlePath = result.SubtitlePath;
                        detectedLanguage = result.DetectedLanguage ?? "auto";

                        _logger.LogInformation($"成功从音频流 {audioStream.Index} 提取字幕，检测到的语言: {detectedLanguage}，共 {result.SegmentCount} 个片段");

                        // 创建最终字幕文件名（使用检测到的语言）
                        var finalFileName = $"{fileName}.{detectedLanguage}.srt";
                        var finalFilePath = Path.Combine(Path.GetDirectoryName(mediaPath), finalFileName);

                        // 如果配置要求保存到媒体目录
                        if (_subtitleConfig.SaveSubtitleToMediaDirectory)
                        {
                            if (File.Exists(finalFilePath))
                            {
                                _logger.LogInformation($"字幕文件已存在媒体目录: {finalFilePath}");
                            }
                            else
                            {
                                _logger.LogInformation($"复制字幕文件到媒体目录: {finalFilePath}");
                                File.Copy(finalSubtitlePath, finalFilePath, true);
                            }
                        }

                        anyStreamProcessed = true;
                        return new Auto_Subtitle(BasicsHelper.GetId())
                        {
                            Name = Path.GetFileName(finalFilePath),
                            VideoId = media.Id,
                            Path = finalFilePath,
                            Language = detectedLanguage,
                            IsDefault = true,
                            IsMediaFile = false,
                            Size = FileHelper.GetFileSize(finalFilePath, 1)
                        };
                    }
                    catch (Exception ex) when (ex.Message.Contains("Failed to load native whisper library") ||
                                               ex.InnerException?.Message?.Contains("Failed to load native whisper library") == true)
                    {
                        // 特殊处理Whisper库加载失败的情况
                        _logger.LogError(ex, $"无法加载Whisper原生库 (平台: {RuntimeInformation.OSDescription})");

                        // 为Linux环境提供更详细的故障排除信息
                        if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                        {
                            _logger.LogWarning("Linux环境下的库加载失败，请尝试:");
                            _logger.LogWarning("1. 安装必要的依赖: sudo apt-get install -y libgomp1");
                            _logger.LogWarning("2. 确保libwhisper.so文件存在并有执行权限");
                            _logger.LogWarning("3. 设置环境变量: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/app/runtimes/linux-x64/native/");

                            // 检查系统库目录
                            _logger.LogInformation("检查系统库目录:");
                            foreach (var path in new[] { "/usr/lib/libwhisper.so", "/usr/lib/x86_64-linux-gnu/libwhisper.so" })
                                _logger.LogInformation($"检查 {path}: {(File.Exists(path) ? "存在" : "不存在")}");
                        }

                        lastException = ex;
                        continue;
                    }
                    catch (DllNotFoundException ex)
                    {
                        // 特殊处理DLL未找到的情况
                        _logger.LogError(ex, $"无法找到所需的库文件: {ex.Message} (平台: {RuntimeInformation.OSDescription})");

                        // 记录详细的路径信息以便调试
                        var assemblyLocation = Assembly.GetExecutingAssembly().Location;
                        var assemblyDirectory = Path.GetDirectoryName(assemblyLocation);
                        var runtimePath = Path.Combine(assemblyDirectory, "runtimes",
                            RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "win" :
                            RuntimeInformation.IsOSPlatform(OSPlatform.Linux)   ? "linux" : "osx",
                            RuntimeInformation.ProcessArchitecture.ToString().ToLower(),
                            "native");

                        _logger.LogInformation($"期望的库文件路径: {runtimePath}");

                        if (Directory.Exists(runtimePath))
                        {
                            var files = Directory.GetFiles(runtimePath);
                            _logger.LogInformation($"目录中的文件: {string.Join(", ", files.Select(Path.GetFileName))}");
                        }
                        else
                        {
                            _logger.LogWarning($"库目录不存在: {runtimePath}");
                        }

                        lastException = ex;
                        continue;
                    }
                    catch (FileNotFoundException ex)
                    {
                        // 特殊处理文件未找到的情况
                        _logger.LogError(ex, $"无法找到所需的文件: {ex.Message} (平台: {RuntimeInformation.OSDescription})");
                        lastException = ex;
                        continue;
                    }
                    catch (Exception ex)
                    {
                        // 记录其他类型的异常
                        _logger.LogError(ex, $"从音频流 {audioStream.Index} 提取字幕失败: {ex.Message} (平台: {RuntimeInformation.OSDescription})");

                        if (ex.InnerException != null)
                        {
                            _logger.LogError(ex.InnerException, $"内部异常: {ex.InnerException.Message}");

                            // 检查内部异常是否包含库加载错误
                            if (ex.InnerException.Message.Contains("Failed to load native whisper library") ||
                                ex.InnerException.GetType() == typeof(DllNotFoundException))
                            {
                                _logger.LogWarning("检测到内部异常可能是库加载问题，请检查libwhisper.so文件");

                                if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) _logger.LogWarning("Linux环境下，可能需要执行: ldconfig -p | grep libwhisper 检查库是否已注册");
                            }
                        }

                        lastException = ex;
                        continue;
                    }
                }
                catch (Exception ex)
                {
                    // 详细记录异常信息，包括内部异常
                    _logger.LogError(ex, $"处理音频流 {audioStream.Index} 时发生错误: {ex.Message} (平台: {RuntimeInformation.OSDescription})");
                    if (ex.InnerException != null) _logger.LogError(ex.InnerException, $"内部异常: {ex.InnerException.Message}");
                    lastException = ex;
                    // 继续尝试下一个音频流
                }

            // 检查是否有任何音频流处理成功
            if (!anyStreamProcessed)
            {
                if (lastException != null)
                {
                    _logger.LogError(lastException, $"所有音频流处理失败，平台: {RuntimeInformation.OSDescription}");

                    // 提供Linux平台特定的提示
                    if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                    {
                        _logger.LogWarning("Linux环境下的故障排除建议:");
                        _logger.LogWarning("1. 确保已安装必要的依赖: sudo apt-get install -y libgomp1");
                        _logger.LogWarning("2. 执行 ldd /path/to/app/runtimes/linux-x64/native/libwhisper.so 检查依赖项");
                        _logger.LogWarning("3. 设置LD_LIBRARY_PATH环境变量指向包含libwhisper.so的目录");
                        _logger.LogWarning("4. 重启应用程序并确保环境变量已生效");
                    }
                }

                return null;
            }

            return null;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"字幕提取过程中发生错误: {ex.Message} (平台: {RuntimeInformation.OSDescription})");
            return null;
        }
    }

    [EventHandler]
    public async Task Handle(StartTranslationOperationCommand command)
    {
        var dataPath = command.data.Path;
        try
        {
            // 检查源文件是否存在
            // 使用正则表达式过滤掉文件路径中的不可视 Unicode 字符串
            // command.data.Path = Path.GetFullPath(command.data.Path);
            if (command.data.IsMediaFile)
            {
                var msg = "--媒体文件提取字幕功能中...";
                _logger.LogInformation(msg);
                var getMediaByIdQuery = new GetMediaByIdQuery(command.data.VideoId);
                await _eventBus.PublishAsync(getMediaByIdQuery);
                //提示文件数据 在线提取元素字幕数据
                var result = await VideoListHelper.ObtainMediaSubtitles(getMediaByIdQuery.Result.MediaType == (int)GlobalVariableEnumConfiguration.MediaEnum.电影, command.data);
                if (result == null)
                {
                    var msgLog = $"--未找到视频{command.data.Name}的字幕文件，无法进行翻译操作！";
                    _logger.LogWarning(msgLog);
                    return;
                }

                dataPath = result.Value.Item1;
                if (result.Value.Item2)
                {
                    //需要修改信息
                    var msgLog = $"--字幕文件{command.data.Name}已存在，需要修改信息！";
                    _logger.LogWarning(msgLog);
                    await _repository.UpdateAsync(result.Value.Item3);
                }
            }

            if (!File.Exists(dataPath))
            {
                _logger.LogError($"--源字幕文件不存在：{dataPath}");
                return;
            }

            // 读取字幕文件
            var subtitleLines = await File.ReadAllLinesAsync(dataPath);
            var translatedLines = new List<string>();
            var isSubtitleContent = false;
            var isHeaderSection = false;
            var subtitleContent = new StringBuilder();
            var originalStyles = new Dictionary<int, string>(); // 存储原始样式
            var currentIndex = 0;

            // 创建翻译后的文件路径
            var directory = Path.GetDirectoryName(dataPath);
            // var fileName = Path.GetFileNameWithoutExtension(dataPath);
            var fileName = Path.GetFileNameWithoutExtension(command.data.Name);

            // 处理文件名，提取基本名称和质量标识（不包含语言标识）
            var extension = Path.GetExtension(dataPath);
            string baseFileName;
            var indexPart = ""; // 保存可能的数字索引部分

            // 如果文件名包含点号，则进行分析
            if (fileName.Contains('.'))
            {
                var parts = fileName.Split('.');

                // 检查最后一部分是否是纯数字（如 a.fre.2.srt 中的 "2"）
                if (parts.Length > 1 && int.TryParse(parts[parts.Length - 1], out _))
                {
                    // 如果最后一部分是纯数字，保存这个索引，并将倒数第二部分视为语言标识
                    indexPart = "." + parts[parts.Length - 1]; // 保存索引，包括前面的点号

                    if (parts.Length > 2)
                        // 丢弃最后两部分（语言和索引），将剩余部分作为基本文件名
                        baseFileName = string.Join(".", parts, 0, parts.Length - 2);
                    else
                        // 如果只有两部分，则第一部分是基本文件名
                        baseFileName = parts[0];
                }
                else
                {
                    // 正常处理：最后一部分是语言标识
                    var lastDotIndex = fileName.LastIndexOf('.');
                    baseFileName = fileName.Substring(0, lastDotIndex);
                }
            }
            // 如果使用旧格式（下划线分隔），则保留最后一个下划线前的所有内容
            else if (fileName.Contains('_'))
            {
                var lastUnderscoreIndex = fileName.LastIndexOf('_');
                baseFileName = fileName.Substring(0, lastUnderscoreIndex);
            }
            else
            {
                baseFileName = fileName;
            }

            var translatedPath = await GetTranslatedSavePath(command.data, $"{baseFileName}.{command.targetLanguage}{indexPart}{extension}") ??
                                 Path.Combine(directory!, $"{baseFileName}.{command.targetLanguage}{indexPart}{extension}");
            // 创建翻译后的文件路径，格式：基本文件名.目标语言[.索引].扩展名
            // var translatedPath = Path.Combine(directory!, $"{baseFileName}.{command.targetLanguage}{indexPart}{extension}");
            // 处理字幕内容
            foreach (var line in subtitleLines)
            {
                // 检查是否是头部区域开始
                if (SubtitleHelp.ScriptInfoRegex.IsMatch(line) || SubtitleHelp.StylesRegex.IsMatch(line) || SubtitleHelp.EventsRegex.IsMatch(line))
                {
                    isHeaderSection = true;
                    translatedLines.Add(line);
                    continue;
                }

                // 如果是头部区域或格式定义行，直接复制
                if (isHeaderSection && (SubtitleHelp.HeaderLineRegex.IsMatch(line) || line.Trim().StartsWith(";")))
                {
                    translatedLines.Add(line);
                    continue;
                }

                // 检查是否结束头部区域
                if (isHeaderSection && string.IsNullOrWhiteSpace(line))
                {
                    isHeaderSection = false;
                    translatedLines.Add(line);
                    continue;
                }

                // 处理正常字幕内容
                if (isHeaderSection) continue;
                if (string.IsNullOrWhiteSpace(line))
                {
                    if (subtitleContent.Length > 0)
                    {
                        await ProcessSubtitleContent(
                            command.data.Language,
                            subtitleContent.ToString().Trim(),
                            currentIndex,
                            originalStyles,
                            translatedLines,
                            command.targetLanguage,
                            dataPath
                        );
                        subtitleContent.Clear();
                    }

                    translatedLines.Add(line);
                    isSubtitleContent = false;
                    continue;
                }

                // 时间轴行直接复制
                if (line.Contains("-->"))
                {
                    translatedLines.Add(line);
                    isSubtitleContent = true;
                    continue;
                }

                // 序号行直接复制
                if (int.TryParse(line, out _))
                {
                    translatedLines.Add(line);
                    continue;
                }

                // 收集字幕内容
                if (isSubtitleContent)
                    subtitleContent.AppendLine(line);
                else
                    translatedLines.Add(line);
            }

            // 处理最后一段字幕内容
            if (subtitleContent.Length > 0)
                await ProcessSubtitleContent(
                    command.data.Language,
                    subtitleContent.ToString().Trim(),
                    currentIndex,
                    originalStyles,
                    translatedLines,
                    command.targetLanguage,
                    dataPath
                );

            // 保存翻译后的文件
            await File.WriteAllLinesAsync(translatedPath, translatedLines);
            command.Result = translatedPath;

            // 更新数据库中的字幕信息
            var subtitleId = BasicsHelper.GetId();
            // 检查生成的ID是否已存在
            var existingSubtitle = await _repository.FindAsync(x => x.Id == subtitleId);
            if (existingSubtitle != null)
            {
                _logger.LogWarning($"生成的字幕ID已存在，重新生成: {subtitleId}");
                subtitleId = BasicsHelper.GetId(); // 重新生成ID
                // 再次检查
                existingSubtitle = await _repository.FindAsync(x => x.Id == subtitleId);
                if (existingSubtitle != null)
                {
                    _logger.LogWarning($"再次生成的字幕ID依然存在，使用时间戳和随机数组合生成ID");
                    subtitleId = $"{DateTime.Now.Ticks}_{Guid.NewGuid():N}";
                    // 第三次检查
                    existingSubtitle = await _repository.FindAsync(x => x.Id == subtitleId);
                    if (existingSubtitle != null)
                    {
                        // 如果极少数情况下仍然冲突，使用更复杂的ID
                        _logger.LogWarning($"第三次生成的字幕ID仍然存在，使用更复杂的唯一ID");
                        subtitleId = $"sub_{DateTime.Now.Ticks}_{Path.GetRandomFileName().Replace(".", "")}_{Guid.NewGuid():N}";
                    }
                }
            }

            // 检查VideoId是否存在，如果不存在则可能需要重新生成一个ID
            var mediaExists = await _mediaRepository.FindAsync(x => x.Id == command.data.VideoId);
            var videoId = command.data.VideoId;

            if (mediaExists == null)
            {
                _logger.LogWarning($"未找到ID为 {videoId} 的媒体记录，这可能导致外键约束问题");
                // 这里可以根据业务逻辑决定是否要生成新的VideoId或者抛出异常
                // 为了保持数据一致性，这里选择生成新的VideoId
                videoId = $"vid_{DateTime.Now.Ticks}_{Guid.NewGuid():N}";
                _logger.LogWarning($"生成新的VideoId: {videoId}");
            }

            var newSubtitle = new Auto_Subtitle(subtitleId)
            {
                Name = Path.GetFileName(translatedPath),
                VideoId = videoId,
                Path = translatedPath,
                Language = command.targetLanguage,
                IsDefault = false,
                IsMediaFile = false,
                Size = FileHelper.GetFileSize(translatedPath, 1)
            };

            try
            {
                _logger.LogInformation($"--添加新字幕记录: ID={subtitleId}, VideoId={videoId}, Path={translatedPath}");
                await _repository.AddAsync(newSubtitle);
                _logger.LogInformation($"--字幕翻译完成：{translatedPath}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"添加字幕记录时发生非约束类错误: {ex.GetType().Name}");
                // 根据业务需求决定是否抛出异常
                throw;
            }

            // 清空翻译缓存，释放内存
            _logger.LogInformation($"--清空翻译缓存，共缓存了 {_translationCache.Count} 个翻译项");
            _translationCache.Clear();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, $"--字幕翻译失败：{dataPath}");
            throw;
        }
    }

    private async Task<string?> GetTranslatedSavePath(Auto_Subtitle commandData, string s)
    {
        var autoMedia = await _mediaRepository.FindAsync(x => x.Id == commandData.VideoId);
        return autoMedia == null ? null : Path.Combine(Path.GetDirectoryName(autoMedia.Path)!, s);
    }

    /// <summary>
    ///     处理字幕内容
    /// </summary>
    /// <param name="dataLanguage"></param>
    /// <param name="content"></param>
    /// <param name="index"></param>
    /// <param name="originalStyles"></param>
    /// <param name="translatedLines"></param>
    /// <param name="targetLanguage"></param>
    /// <param name="path"></param>
    private async Task ProcessSubtitleContent(string? dataLanguage, string content,
        int index,
        Dictionary<int, string> originalStyles,
        List<string> translatedLines,
        string targetLanguage,
        string path)
    {
        var (cleanText, style) = SubtitleHelp.ExtractStyleAndContent(content);
        if (!string.IsNullOrWhiteSpace(style)) originalStyles[index] = style;

        // 创建缓存键
        var cacheKey = $"{dataLanguage}:{targetLanguage}:{cleanText}";
        string translatedText;

        // 检查是否已经翻译过这段文本
        if (_translationCache.TryGetValue(cacheKey, out var cachedTranslation))
        {
            // 如果找到缓存的翻译，直接使用
            translatedText = cachedTranslation;
            _logger.LogDebug($"使用缓存翻译: '{cleanText}' -> '{translatedText}'");
        }
        else
        {
            // 如果没有缓存，进行翻译
            translatedText = await TranslateText(dataLanguage, cleanText, targetLanguage, path, true);
            // 存储翻译结果到缓存
            _translationCache[cacheKey] = translatedText;
            _logger.LogDebug($"新翻译添加到缓存: '{cleanText}' -> '{translatedText}'");
        }

        if (originalStyles.TryGetValue(index, out var originalStyle))
            translatedText = SubtitleHelp.RestoreStyle(translatedText, originalStyle);

        translatedLines.Add(translatedText);
    }

    /// <summary>
    ///     具体文字翻译
    /// </summary>
    /// <param name="dataLanguage">本身语言</param>
    /// <param name="text">文字</param>
    /// <param name="targetLanguage">翻译语言</param>
    /// <param name="path">来源的地址</param>
    /// <param name="shouldAddToDatabase">是否应添加到数据库，缓存命中时应为false</param>
    /// <returns></returns>
    /// <exception cref="NotSupportedException"></exception>
    private async Task<string> TranslateText(string? dataLanguage, string text, string targetLanguage, string path, bool shouldAddToDatabase = true)
    {
        try
        {
            var getTranslationCommand = new GetTranslationCommand(dataLanguage, text, targetLanguage, path);
            if (!shouldAddToDatabase)
                // 如果不需要添加到数据库（即缓存命中），设置标志位
                getTranslationCommand.IsAdd = false;
            await _eventBus.PublishAsync(getTranslationCommand);
            return getTranslationCommand.Result;
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }
    }

    [EventHandler]
    public async Task Handle(GetSubtitlesByListQuery command)
    {
        var data = new List<TextTranslationDto>();
        foreach (var item in command.data.value)
        {
            var getTranslationCommand = new GetTranslationCommand(command.data.languageType, item, command.data.translatedLanguageTyp, null);
            await _eventBus.PublishAsync(getTranslationCommand);
            data.Add(new TextTranslationDto()
            {
                Text = getTranslationCommand.Result,
                IsTranslated = getTranslationCommand.IsDid
            });
        }

        command.Result = data;
    }


    [EventHandler]
    public async Task Handle(StartSubtitleTranslationExtractionCommand command)
    {
        //判断是否来自同一个媒体
        if (command.data1.VideoId != command.data2.VideoId) throw new Exception("字幕翻译提取失败，字幕来源不是同一个媒体！");

        //判断是否来自同一个媒体
        if (command.data1.Language == null || command.data2.Language == null) throw new Exception("字幕翻译提取失败，字幕语言为空！");
        //判断是否是同一个语言
        if (command.data1.Language == command.data2.Language) throw new Exception("字幕翻译提取失败，字幕语言一致！");
        //分别提取字幕中的时间跟内容
        // 检查文件是否存在
        var path = command.data1.Path;
        var path2 = command.data2.Path;
        var media = await _mediaRepository.FindAsync(x => x.Id == command.data1.VideoId) ?? throw new Exception("未找到媒体文件");
        using var source = new CancellationTokenSource();

        var task1 = Task.Run(async () =>
        {
            if (command.data1.IsMediaFile || !File.Exists(path))
            {
                //凭借提取缓存地址是否存在
                var cachePath = VideoListHelper.GetCachePath(media.MediaType == (int)GlobalVariableEnumConfiguration.MediaEnum.电影);
                cachePath = cachePath + "/" + command.data1.Name[..command.data1.Name.LastIndexOf('.')] + "." + command.data1.Language + "." + command.data1.Index +
                            Common.DefaultSrt;
                if (!Directory.Exists(cachePath))
                {
                    if (!command.data1.IsMediaFile) throw new Exception("未找到字幕文件");
                    var result = await VideoListHelper.ObtainMediaSubtitles(media.MediaType == (int)GlobalVariableEnumConfiguration.MediaEnum.电影, command.data1, source) ??
                                 throw new Exception("未找到字幕文件");
                    cachePath = result.Item1;
                }

                path = cachePath;
            }
        });
        var task2 = Task.Run(async () =>
        {
            if (command.data2.IsMediaFile || !File.Exists(path2))
            {
                //凭借提取缓存地址是否存在
                var cachePath = VideoListHelper.GetCachePath(media.MediaType == (int)GlobalVariableEnumConfiguration.MediaEnum.电影);
                cachePath = cachePath + "/" + command.data2.Name[..command.data2.Name.LastIndexOf('.')] + "." + command.data2.Language + "." + command.data2.Index +
                            Common.DefaultSrt;
                if (!Directory.Exists(cachePath))
                {
                    if (!command.data2.IsMediaFile)
                        throw new Exception("未找到字幕文件");
                    var result = await VideoListHelper.ObtainMediaSubtitles(media.MediaType == (int)GlobalVariableEnumConfiguration.MediaEnum.电影, command.data2, source) ??
                                 throw new Exception("未找到字幕文件");
                    cachePath = result.Item1;
                }

                path2 = cachePath;
            }
        });
        //任务异常捕获
        try
        {
            await Task.WhenAll(task1, task2);
        }
        catch (Exception ex)
        {
            source.Cancel();
            throw new Exception(ex.Message);
        }


        if (path == path2) throw new Exception("字幕翻译提取失败，字幕文件一致！");
        if (path == null || path2 == null) throw new Exception("字幕翻译提取失败，字幕文件为空！");
        var subtitle1 = SubtitleHelp.ParseSubtitleFile(path);
        var subtitle2 = SubtitleHelp.ParseSubtitleFile(path2);
        if (subtitle1 == null || subtitle2 == null) throw new Exception("字幕翻译提取失败，字幕文件解析失败！");
        //创建对应的 字幕翻译记录
        var data = new List<Auto_Translate>();
        foreach (var item in subtitle1)
        {
            //根据开始时间查询，如果开始时间相同，就进行翻译 时间精确到秒 不精确到毫秒 StartTime是TimeSpan类型
            // ... existing code ...
            var sub2 = subtitle2.FirstOrDefault(x =>
                TimeSpan.FromSeconds(Math.Floor(x.StartTime.TotalSeconds)) ==
                TimeSpan.FromSeconds(Math.Floor(item.StartTime.TotalSeconds)));
            // var sub2 = subtitle2.FirstOrDefault(x => x.StartTime.ToString("HH:mm:ss") == startTime);
            if (sub2 == null) continue;
            //如果内容有换行，就不进行翻译
            if (item.Content.Contains('\n')) continue;
            if (item.Content.Contains('\r')) continue;
            var isNormal = true;
            var isNormal2 = true;
            //如果内容带有 [],() 等符号，就不进行翻译
            if (Common.SplitRegex.IsMatch(item.Content))
            {
                //如果是结尾有符号
                if (!Common.NormalRegex.IsMatch(item.Content))
                    continue;
                //判断符号是否再结尾
                var lastChar = item.Content[^1];
                if (Common.CommonRegex.IsMatch(lastChar.ToString())) isNormal = false;
                continue;
            }

            if (Common.SplitRegex.IsMatch(sub2.Content))
            {
                //如果是结尾有符号
                if (!Common.NormalRegex.IsMatch(sub2.Content))
                    continue;
                if (Common.CommonRegex.IsMatch(sub2.Content[^1].ToString())) isNormal2 = false;
                continue;
            }

            if (!isNormal && isNormal == isNormal2) continue;
            //判断是否存在
            var result = await _translateRepository.FindAsync(x =>
                x.LanguageType == command.data1.Language && x.TranslatedLanguageType == command.data2.Language && x.Value == item.Content);
            if (result != null) continue;
            var result2 = await _translateRepository.FindAsync(x =>
                x.LanguageType == command.data2.Language && x.TranslatedLanguageType == command.data1.Language && x.Value == sub2.Content);
            if (result2 != null) continue;
            //判断是否已经存在data中
            if (data.Any(x => x.Value == item.Content)) continue;
            data.Add(new Auto_Translate(BasicsHelper.GetId())
            {
                LanguageType = command.data1.Language,
                Value = item.Content,
                TranslatedLanguageType = command.data2.Language,
                TranslatedValue = sub2.Content,
                TriggerCount = 0,
                CreateTime = DateTime.Now,
                Source = command.data1.Name,
                SourcePath = path,
                TargetPath = path2
            });
        }

        if (data.Count > 0)
        {
            await _translateRepository.AddDataAsync(data);
            await _translateRepository.UnitOfWork.SaveChangesAsync();
            await _translateRepository.UnitOfWork.CommitAsync();
            var msg = $"--自动翻译字幕 完成，翻译数量：{data.Count}";
            _logger.LogInformation(msg);
        }
    }
}